package com.boxin.ims.modules.wechat.utils;

import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import com.boxin.framework.base.utils.DateUtils;
import com.boxin.ims.modules.wechat.entity.ReturnResult;
import com.boxin.ims.modules.wechat.entity.Seckill;
import com.boxin.ims.modules.wechat.entity.SeckillConfig;
import com.boxin.ims.modules.wechat.entity.SeckillGainer;
import com.boxin.ims.modules.wechat.entity.WechatMember;
import com.boxin.ims.modules.wechat.service.SeckillConfigService;
import com.boxin.ims.modules.wechat.service.SeckillGainerService;
import com.boxin.ims.modules.wechat.service.SeckillService;
import com.google.common.collect.Maps;
import com.thinkgem.jeesite.modules.sys.security.SystemRealm.Principal;

@Service
public class SeckillUtils implements ApplicationContextAware{
	
	private final static String PREX_SECKILL_KEY = "SECKILL_";		//Seckill 缓存 ID前缀
	private final static String PREX_SECKILL_CONFIG_KEY = "SECKILL_CONFIG_";		//Seckill 缓存 ID前缀
	
	private static SeckillService seckillService;
	
	private static SeckillGainerService seckillGainerService;
	
	private static SeckillConfigService seckillConfigService;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		
		   seckillService  = (SeckillService)applicationContext.getBean("seckillService");
		   seckillGainerService  = (SeckillGainerService)applicationContext.getBean("seckillGainerService");
		   seckillConfigService  = (SeckillConfigService)applicationContext.getBean("seckillConfigService");
	}
	
	
	/**
	 * @author Jakemanse
	 * @time 2013-9-14  上午12:23:11
	 * @function <p> 秒杀处理  </p>
	 * @param seckill	秒杀产品信息
	 * @param member	会员
	 */
	public static synchronized ReturnResult doSeckill(Seckill seckill,WechatMember member){
		ReturnResult  rreResult = new ReturnResult();
		rreResult.setSuccess(false);
		rreResult.setInfo("亲，您没有秒杀到奖品，感谢您参与~~");
		
		seckill = getSeckillById(seckill.getId());	//seckill实体信息
		
		if(Seckill.PUBLISH_FLAG_YES.equals(seckill.getPubFlag())){	//已发布
			
			if(Seckill.DEL_FLAG_NORMAL.equals(seckill.getDelFlag()) && Seckill.PUBLISH_FLAG_YES.equals(seckill.getPubFlag()) && seckill.getAmount() >0){	//还没有被秒杀掉
				//判断该会员是否已经秒杀过
				SeckillGainer sg = new SeckillGainer();
				sg.setStatus(SeckillGainer.STATUS_NORMAL);
				sg.setSeckill(seckill);
				sg.setMember(member);
				List<SeckillGainer>  result = 	seckillGainerService.find(sg);
				if(result != null && !result.isEmpty()){	//本会员已经有一个未核销的秒钉奖品，本次不再进行秒杀
					rreResult.setInfo("亲，您不能重复参与秒杀活动，请将上次秒中的宝贝使用后再参与本次秒杀活动，感谢您的支持！");
					rreResult.setParam(null);
					rreResult.setSuccess(false);
					return rreResult;
				}
				
				seckill.setAmount(seckill.getAmount()-1);
				putCache(PREX_SECKILL_KEY+seckill.getId(), seckill);
				//更新数据库
				seckillService.save(seckill);	//秒杀物品信息
				
				//添加秒杀成功者入库
				member = WechatUtils.getWechatMemberByOpenId(member.getUser(), member.getWechatId());	//获得已绑定的会员信息
				SeckillConfig config = getSeckillConfigByUserId(member.getUser().getId());
				SeckillGainer seckillGainer = new SeckillGainer();
				seckillGainer.setMember(member);
				seckillGainer.setUser(member.getUser());
				seckillGainer.setName(seckill.getName());
				seckillGainer.setUserName(member.getName());
				seckillGainer.setSeckill(seckill);
				if(config == null) config = new SeckillConfig();
				seckillGainer.setEndTime(DateUtils.getDelayDate(config.getValidDays()));
				seckillGainerService.save(seckillGainer);
				
				//扣除积分,暂时不扣分
//				if(config.getCost()){
//					ScoreUtils.addScore(member, config.getCostScore(), "参与秒杀中奖扣除积分");
//				}
				
				rreResult.setInfo("恭喜您，秒杀成功.");
				rreResult.setParam(seckillGainer);
				rreResult.setSuccess(true);
				
				return rreResult;
			}else if(Seckill.DEL_FLAG_KILL.equals(seckill.getDelFlag())){	//已被秒杀掉
				
			}else{	//其它情况，或作废或删除
				
			}
		}else{
			
		}
		
		return rreResult;
		
	}
	
	
	public static SeckillConfig getSeckillConfigByUserId(Long userId){
		SeckillConfig seckillConfig = (SeckillConfig) getCache(PREX_SECKILL_CONFIG_KEY+userId);
		if(seckillConfig == null){
			seckillConfig = seckillConfigService.getByUserId(userId);
			if(seckillConfig != null){
				putCache(PREX_SECKILL_CONFIG_KEY+userId, seckillConfig);
			}
		}
		
		return seckillConfig;
	}
	
	/**
	 * @author Jakemanse
	 * @time 2013-9-16  上午9:52:26
	 * @function <p> 放Seckill放入内存 </p>
	 * @param id
	 * @return
	 */
	public static Seckill getSeckillById(Long id){
		Seckill seckill = (Seckill) getCache(PREX_SECKILL_KEY+id);
		if(seckill == null){
			seckill = seckillService.get(id);
			if(seckill != null){
				putCache(PREX_SECKILL_KEY+id, seckill);
			}
		}
		
		return seckill;
	}
	
	
	
	
	
	
	public static Object getCache(String key) {
		return getCache(key, null);
	}
	
	public static Object getCache(String key, Object defaultValue) {
		Object obj = getCacheMap().get(key);
		return obj==defaultValue?defaultValue:obj;
	}
	
	public static void putCache(String key, Object value) {
		getCacheMap().put(key, value);
	}
	
	public static void removeCache(String key) {
		getCacheMap().remove(key);
	}
	
	private static Map<String, Object> getCacheMap(){
		Map<String, Object> map = Maps.newHashMap();
		try{
			Subject subject = SecurityUtils.getSubject();
			Principal principal = (Principal)subject.getPrincipal();
			return principal!=null?principal.getCacheMap():map;
		}catch (UnavailableSecurityManagerException e) {
			return map;
		}
	}

}
